package gateway

import (
	"context"
	assetfs "github.com/elazarl/go-bindata-assetfs"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"github.com/zeromicro/go-zero/core/logx"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	gw "mall/services/product/rpc/pb"
	"mall/services/product/rpc/swagger"
	"net/http"
	"path"
	"strconv"
	"strings"
)

func NewSwaggerUI(ctx context.Context, endpoint string, exportPort int) error {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	gwMux, err := newGateway(ctx, endpoint)
	if err != nil {
		panic(err)
	}
	mux := http.NewServeMux()
	mux.Handle("/", gwMux)
	mux.HandleFunc("/swagger/", serveSwaggerFile)
	serveSwaggerUI(mux)

	logx.Infof("grpc-gateway listen on localhost:%d", exportPort)
	return http.ListenAndServe(":"+strconv.Itoa(exportPort), mux)
}

func newGateway(ctx context.Context, endpoint string) (http.Handler, error) {
	gwMux := runtime.NewServeMux()
	credentials := insecure.NewCredentials()
	opts := []grpc.DialOption{grpc.WithTransportCredentials(credentials)}
	if err := gw.RegisterProductAttrFacadeHandlerFromEndpoint(ctx, gwMux, endpoint, opts); err != nil {
		return nil, err
	}

	return gwMux, nil
}

func serveSwaggerFile(w http.ResponseWriter, r *http.Request) {
	logx.Info("start serveSwaggerFile")

	if !strings.HasSuffix(r.URL.Path, "swagger.json") {
		logx.Infof("Not Found: %s", r.URL.Path)
		http.NotFound(w, r)
		return
	}

	p := strings.TrimPrefix(r.URL.Path, "/swagger/")
	p = path.Join("./services/product/rpc/swagger", p)

	logx.Infof("Serving swagger-file: %s", p)

	http.ServeFile(w, r, p)
}

func serveSwaggerUI(mux *http.ServeMux) {
	fileServer := http.FileServer(&assetfs.AssetFS{
		Asset:    swagger.Asset,
		AssetDir: swagger.AssetDir,
		Prefix:   "third_party/swagger-ui",
	})
	prefix := "/swagger-ui/"
	mux.Handle(prefix, http.StripPrefix(prefix, fileServer))
}
